#ifndef __PCD_API_H
#define __PCD_API_H

#include <dicom/dicom.h>
#include <dicom/list.h>

#ifdef WIN32
#include <windows.h>
#else
#include <semaphore.h>
#endif

#define PCD_DEV                    "/dev/ttySAC1"

/* Recv command set */
#define RCMD_JOIN                  0x01
#define RCMD_REPORT                0x02
# define REPORT_TYPE_VOLT          0
# define REPORT_TYPE_CURR          1
# define REPORT_TYPE_INSTPWR       2
# define REPORT_TYPE_ACCPWR        3
#define RCMD_MAC                   0x03
#define RCMD_STATUS                0x04
#define RCMD_EVENT                 0x05
#define RCMD_AUTO_REPORT           0x06
#define RCMD_COORD_ACK             0x07
#define RCMD_ALARM                 0xff

/* Send command set */
#define TCMD_REPORT_REQ            0x81
#define TCMD_SET_AUTO_REPORT_TIMER 0x82
#define TCMD_REPORT_SELECT         0x83
# define REPORT_SEL_VOLT           0x1
# define REPORT_SEL_CURR           0x2
# define REPORT_SEL_INSTPWR        0x4
# define REPORT_SEL_ACCPWR         0x8
#define TCMD_TIMER_ON              0x84
#define TCMD_TIMER_OFF             0x85
#define TCMD_MAC_REQ               0x86
#define TCMD_STATUS_REQ            0x87
#define TCMD_SET_MAX_VOLT          0xff
#define TCMD_SET_MIN_VOLT          0xff
#define TCMD_SET_MAX_CURR          0xff
#define TCMD_SET_MIN_CURR          0xff

/* Error codes */
#define ERROR_INVALID_POINTER      -1
#define ERROR_BAD_ADDRESS          -2
#define ERROR_BAD_COMMAND          -3
#define ERROR_BAD_LENGTH           -4
#define ERROR_BAD_CHECKSUM         -5


struct pcd_raw_pkt {
    u_int8 start[4];
    u_int16 address;
    u_int8 command;
    u_int8 length;
    u_int8 data[255];
    u_int8 checksum;
};

struct pcd_report_data {
    u_int16 voltage;
    u_int16 current;
    u_int16 instant_power;
    u_int16 accum_power;
};

struct pcd_struct {
    struct list_head list_node;
    u_int8 command;
    u_int16 id;   /* Known as 'address' in raw packet */
    char mac_addr[24];
    u_int16 time_left;
    u_int8 status;
    u_int8 event;
    /* u_int8 alarm; */
    u_int8 ack;
    struct pcd_report_data reports;
    char last_update[20];
    char *description;
#ifdef WIN32
    HANDLE semaphore;
#else
    sem_t semaphore;
#endif
};

void pcd_open(const char *pcd_dev);
void pcd_close(void);
int pcd_read_raw_packet(struct pcd_raw_pkt *packet);
int pcd_write_raw_packet(struct pcd_raw_pkt *packet);
struct pcd_struct *pcd_read_packet(void);
void pcd_report_request(u_int16 address);
void pcd_set_autoreport_timer(u_int16 address, u_int16 time);
void pcd_report_type_select(u_int16 address, u_int16 selection);
void pcd_set_turnon_timer(u_int16 address, u_int16 time);
void pcd_set_turnoff_timer(u_int16 address, u_int16 time);
void pcd_mac_request(u_int16 address);
void pcd_status_request(u_int16 address);
/*
void pcd_set_max_volt(u_int16 address, u_int16 volt);
void pcd_set_min_volt(u_int16 address, u_int16 volt);
void pcd_set_max_curr(u_int16 address, u_int16 curr);
void pcd_set_min_curr(u_int16 address, u_int16 curr);
*/

int pcd_list_insert(struct pcd_struct *pcd);
struct pcd_struct *pcd_list_search_by_id(u_int16 id);
struct pcd_struct *pcd_list_search_by_mac(char *mac);

#endif

